local EVENTS_TO_DISPLAY = 30
local TRACKS_TO_DISPLAY = 20
local ASSIGNED_TRACKS_TO_DISPLAY = 8
EVENTS_ITEM_HEIGHT = 16

--DEBUG = 1

local self = 
{
    SelectedEventsTable = nil,
}

local eventTypes = 
{ 
    "Event Script",
    "Update Script",
    "Buff"
}

function SoundtrackFrame_AddNamedBoss(targetName)
    Soundtrack.AddEvent("Boss", targetName, 7, true)
    SoundtrackFrame_SelectedEvent = targetName
    SoundtrackFrame_RefreshEvents()
end

StaticPopupDialogs["SOUNDTRACK_ADD_BOSS"] = {
    text = "Add named mob:",
    button1 = TEXT(ACCEPT),
    button2 = TEXT(CANCEL),
    hasEditBox = 1,
    maxLetters = 100,
    OnAccept = function()
        local editBox = getglobal(this:GetParent():GetName().."EditBox")
        SoundtrackFrame_AddNamedBoss(editBox:GetText())
    end,
    OnShow = function()
        getglobal(this:GetName().."EditBox"):SetFocus()
    end,
    OnHide = function()
        if ( ChatFrameEditBox:IsVisible() ) then
            ChatFrameEditBox:SetFocus()
        end
        getglobal(this:GetName().."EditBox"):SetText("")
    end,
    EditBoxOnEnterPressed = function()
        local editBox = getglobal(this:GetParent():GetName().."EditBox")
        SoundtrackFrame_AddNamedBoss(editBox:GetText())
        this:GetParent():Hide()
    end,
    EditBoxOnEscapePressed = function()
        this:GetParent():Hide()
    end,
    timeout = 0,
    exclusive = 1,
    whileDead = 1,
    hideOnEscape = 1
}

function Soundtrack.IndexOf(_table, value)
    if _table == nil then
        return 0
    end
    
    for i = 1, getn(_table) do
        if _table[i] == value then
            return i
        end
    end
    
    return 0
end 

local eventSubFrames = 
{ 
    "SoundtrackFrameAssignedTracks", 
    "SoundtrackFrame_EventSettings" 
}

function SoundtrackFrame_ShowSubFrame(frameName)
    for index, value in ipairs(eventSubFrames) do
        if value == frameName then
            getglobal(value):Show()
        else
            getglobal(value):Hide()
        end    
    end 
end

function SoundtrackFrame_RefreshEventSettings()
end

function SoundtrackFrame_OnSelectedEventTabChanged()
    if SoundtrackFrame.showAssignedFrame then
        SoundtrackFrame_ShowSubFrame("SoundtrackFrameAssignedTracks")
        SoundtrackFrame_RefreshAssignedTracks()
    else
        SoundtrackFrame_ShowSubFrame("SoundtrackFrame_EventSettings")
        SoundtrackFrame_RefreshEventSettings()
    end
end

SoundtrackFrame_SelectedEvent = nil
SoundtrackFrame_SelectedTrack = nil

local function GetFlatEventsTable()
    return Soundtrack_FlatEvents[self.SelectedEventsTable]
end

local suspendRenameEvent = false

function SoundtrackFrame_OnLoad()
    SoundtrackFrame.showAssignedFrame = true

    tinsert(UISpecialFrames, "SoundtrackFrame")
    
    PanelTemplates_SetNumTabs(this, 8)
    PanelTemplates_UpdateTabs(this)
    
    PanelTemplates_SetTab(SoundtrackFrame, 1)
end

function SoundtrackFrame_OnEvent(arg1, arg2)
end

local function RefreshEventSettings()

    if SoundtrackFrame_SelectedEvent then
        suspendRenameEvent = true
        getglobal("SoundtrackFrame_EventName"):SetText(SoundtrackFrame_SelectedEvent)
        suspendRenameEvent = false
        
        local eventTable = Soundtrack.Events.GetTable(self.SelectedEventsTable)
        local event = eventTable[SoundtrackFrame_SelectedEvent]
        if event then
            SoundtrackFrame_RandomCheckButton:SetChecked(event.random)
            SoundtrackFrame_ContinuousCheckBox:SetChecked(event.continuous)
            SoundtrackFrame_SoundEffectCheckBox:SetChecked(event.soundEffect)
        end 
    end
end

local function GetTabIndex(tableName)
    if (tableName == "Battle") then 
        return 1
    elseif (tableName == "Zone") then 
        return 2
    elseif (tableName == "Dance") then 
        return 3
    elseif (tableName == "Misc") then 
        return 4
    elseif (tableName == "Custom") then
        return 5
    elseif (tableName == "Playlists") then
        return 6
    else 
        return 0
    end
end

-- Makes sure we select the correct tab that
-- contains the currently playing event.
local function SelectActiveTab()
    local stackLevel = Soundtrack.Events.GetCurrentStackLevel()
    
    if stackLevel > 0 then
        -- Select currently playing table tab
        local tableName = Soundtrack.Events.Stack[stackLevel].tableName
        self.SelectedEventsTable = tableName
        PanelTemplates_SetTab(SoundtrackFrame, GetTabIndex(tableName))
    elseif not self.SelectedEventsTable then
        -- Select the first tab
        self.SelectedEventsTable = "Battle"
        PanelTemplates_SetTab(SoundtrackFrame, 1)
    end
    
    SoundtrackFrame_OnTabChanged()
end

function SoundtrackFrame_StatusBarSetProgress(statusBarID, max, current)

    -- Skill bar objects
    local statusBar = getglobal(statusBarID)
    local statusBarBackground = getglobal(statusBarID.."Background")
    local statusBarFillBar = getglobal(statusBarID.."FillBar")
    local statusBarLabel = getglobal(statusBarID.."Text1")

    statusBarFillBar:Hide()
    statusBarBackground:Hide()
    
    -- Set bar color depending on skill cost
    if max then
        statusBar:SetStatusBarColor(0.0, 0.75, 0.0, 0.5)
        statusBarBackground:SetVertexColor(0.0, 0.5, 0.0, 0.5)
        statusBarFillBar:SetVertexColor(0.0, 1.0, 0.0, 0.5)
    else   
        statusBar:SetStatusBarColor(0.25, 0.25, 0.25)
        statusBar:SetMinMaxValues(0, 0)
        statusBar:SetValue(1)
        statusBarBackground:SetVertexColor(0.75, 0.75, 0.75, 0.5)
    
        --statusBar:SetStatusBarColor(0.5, 0.5, 0.5, 0.5)
        --statusBarBackground:SetVertexColor(0.5, 0.5, 0.5, 0.5)
        statusBarFillBar:Hide()
        --statusBarFillBar:SetVertexColor(1.0, 1.0, 1.0, 0.5) 
        return
    end
    
    statusBar:SetMinMaxValues(0, max)
    statusBar:SetValue(current)
    if current <= max and max ~= 0 then
        local fillBarWidth = (current / max) * (statusBar:GetWidth() - 4)
        statusBarFillBar:SetPoint("TOPRIGHT", statusBarLabel, "TOPLEFT", fillBarWidth, 0)
        statusBarFillBar:Show()
    else
        statusBarFillBar:Hide()
    end
end

function SoundtrackFrame_RefreshTrackProgress()
    if not Soundtrack.Library.CurrentlyPlayingTrack then
        SoundtrackFrame_StatusBarSetProgress("SoundtrackFrame_StatusBarTrack", nil, nil)
        SoundtrackFrame_StatusBarSetProgress("SoundtrackControlFrame_StatusBarTrack", nil, nil)
        return
    end
    
    local track = Soundtrack_Tracks[Soundtrack.Library.CurrentlyPlayingTrack]
    if not track then
        SoundtrackFrame_StatusBarSetProgress("SoundtrackFrame_StatusBarTrack", nil, nil)
        SoundtrackFrame_StatusBarSetProgress("SoundtrackControlFrame_StatusBarTrack", nil, nil)
        return
    end
    
    local timer = Soundtrack.Timers.Get("FadeOut")
    local currentTime = 0
    local duration = track.length
    if timer then
        currentTime = GetTime() - timer.Start 
    end

    local textRemain = Soundtrack.Util.FormatDuration(duration - currentTime)
    SoundtrackFrame_StatusBarTrackText2:SetText(textRemain)
    SoundtrackControlFrame_StatusBarTrackText2:SetText(textRemain)
    
    SoundtrackFrame_StatusBarSetProgress("SoundtrackFrame_StatusBarTrack", duration, currentTime)
    SoundtrackFrame_StatusBarSetProgress("SoundtrackControlFrame_StatusBarTrack", duration, currentTime)
end


local function SoundtrackFrame_RefreshCurrentlyPlaying()
        
    
    -- Refresh event
    local stackLevel = Soundtrack.Events.GetCurrentStackLevel()
    local currentTrack = Soundtrack.Library.CurrentlyPlayingTrack
     
    if stackLevel == 0 then
        SoundtrackFrame_StatusBarEventText1:SetText("No event playing")
        SoundtrackFrame_StatusBarEventText2:SetText("")
        SoundtrackFrame_StatusBarSetProgress("SoundtrackFrame_StatusBarEvent", nil, nil)
        SoundtrackFrame_StatusBarSetProgress("SoundtrackControlFrame_StatusBarEvent", nil, nil)
    else
        local tableName = Soundtrack.Events.Stack[stackLevel].tableName
        local eventName = Soundtrack.Events.Stack[stackLevel].eventName
        SoundtrackFrame_StatusBarEventText1:SetText(Soundtrack.GetPathFileName(eventName))
        local event = Soundtrack.GetEvent(tableName, eventName)
        
        if event and event.tracks then
            local numTracks = getn(event.tracks)
            
            if Soundtrack.Library.CurrentlyPlayingTrack then
                local curTrackIndex = Soundtrack.IndexOf(event.tracks, currentTrack)
                SoundtrackFrame_StatusBarEventText2:SetText(curTrackIndex .. " / " .. numTracks)
                SoundtrackFrame_StatusBarSetProgress("SoundtrackFrame_StatusBarEvent", numTracks, curTrackIndex)
                SoundtrackFrame_StatusBarSetProgress("SoundtrackControlFrame_StatusBarEvent", numTracks, curTrackIndex)
            else
                SoundtrackFrame_StatusBarEventText2:SetText(numTracks .. " tracks")
            end
        else
            SoundtrackFrame_StatusBarEventText2:SetText("")
        end
        
    end
    
    -- Refresh track
    --if currentTrack == nil then
    --   Soundtrack.TraceFrame("Refreshing track: " .. "nil")
    --else
    --   Soundtrack.TraceFrame("Refreshing track: " .. currentTrack)
    --end
    local track = Soundtrack_Tracks[currentTrack]
    if not track then
        SoundtrackFrame_StatusBarTrackText1:SetText("No tracks playing")
        SoundtrackFrame_StatusBarTrackText2:SetText("")
    else
        if SoundtrackFrame.nameHeaderType == "filePath" then
            SoundtrackFrame_StatusBarTrackText1:SetText(currentTrack)
        elseif SoundtrackFrame.nameHeaderType == "fileName" then
            SoundtrackFrame_StatusBarTrackText1:SetText(Soundtrack.GetPathFileName(currentTrack))
        else
            if track.title == nil or track.title == "" then
                SoundtrackFrame_StatusBarTrackText1:SetText(currentTrack)
            else
                SoundtrackFrame_StatusBarTrackText1:SetText(track.title)
            end
        end
        
        
        -- Fetch current track time from "FadeOut" event
        SoundtrackFrame_RefreshTrackProgress()
    end
    
    -- Refresh control frame too
    SoundtrackControlFrame_StatusBarEventText1:SetText(SoundtrackFrame_StatusBarEventText1:GetText())
    SoundtrackControlFrame_StatusBarEventText2:SetText(SoundtrackFrame_StatusBarEventText2:GetText())
    SoundtrackControlFrame_StatusBarTrackText1:SetText(SoundtrackFrame_StatusBarTrackText1:GetText())
    SoundtrackControlFrame_StatusBarTrackText2:SetText(SoundtrackFrame_StatusBarTrackText2:GetText())
end

SOUNDTRACKFRAME_COLUMNHEADERNAME_LIST = 
{
    { name = "File Path", type = "filePath" },
    { name = "File Name", type = "fileName" },
    { name = "Title", type = "title" }
}


function SoundtrackFrame_ColumnHeaderNameDropDown_OnClick()
    UIDropDownMenu_SetSelectedID(SoundtrackFrame_ColumnHeaderNameDropDown, this:GetID())
    SoundtrackFrame.nameHeaderType = SOUNDTRACKFRAME_COLUMNHEADERNAME_LIST[this:GetID()].type
    Soundtrack.TraceFrame("Refreshing tracks with " .. SoundtrackFrame.nameHeaderType)
    if this.sortType == "name" and 
       Soundtrack.Settings.TrackSortingCriteria == "fileName" or 
       Soundtrack.Settings.TrackSortingCriteria == "filePath" or 
       Soundtrack.Settings.TrackSortingCriteria == "title" then 
        Soundtrack.SortTracks(SoundtrackFrame.nameHeaderType)
    else
        Soundtrack.SortTracks(this.sortType)
    end
    
    --SoundtrackFrame_RefreshCurrentlyPlaying()
end

function SoundtrackFrame_ColumnHeaderNameDropDown_Initialize()
    --Soundtrack.TraceFrame("Track sorting criteria: " .. Soundtrack.Settings.TrackSortingCriteria)

    local info = UIDropDownMenu_CreateInfo()
    for i=1, getn(SOUNDTRACKFRAME_COLUMNHEADERNAME_LIST), 1 do
        info.text = SOUNDTRACKFRAME_COLUMNHEADERNAME_LIST[i].name
        info.func = SoundtrackFrame_ColumnHeaderNameDropDown_OnClick
        local checked = nil
        --[[if Soundtrack.Settings.TrackSortingCriteria == info.text then
            Soundtrack.TraceFrame(info.Text .. " is checked!")
            checked = true
        end
        info.checked = checked]]
        UIDropDownMenu_AddButton(info)
    end
end



-- Functions to call from outside, to refresh the UI partially
function SoundtrackFrame_TouchEvents()
    
    SoundtrackFrame_RefreshCurrentlyPlaying()
    
    -- Refresh stack
    local stackLevel = Soundtrack.Events.GetCurrentStackLevel()
    local currentEvent = "None"
    if stackLevel ~= 0 then
        currentEvent = Soundtrack.Events.Stack[stackLevel].eventName
    end
    
    local i
    for i = 1, Soundtrack.MaxStackLevel, 1 do
        local tableName = Soundtrack.Events.Stack[i].tableName
        local eventName = Soundtrack.Events.Stack[i].eventName
        local label = getglobal("SoundtrackControlFrameStack"..i)
        if not eventName then
            label:SetText(i..") None")
        else
            local playOnceText
            local event = Soundtrack.GetEvent(tableName, eventName)
            if event.continuous then
                playOnceText = "Loop"
            else
                playOnceText = "Once"
            end
            local eventText = Soundtrack.GetPathFileName(eventName)
            label:SetText(i..") "..eventText.." ("..playOnceText..")")
        end
    end

    SoundtrackFrame_RefreshEvents()
end

-- Functions to call from outside, to refresh the UI partially
function SoundtrackFrame_TouchTracks()
    SoundtrackFrame_RefreshTracks()
    SoundtrackFrame_RefreshCurrentlyPlaying()
end

function SoundtrackFrame_RefreshOptionsFrame()
    local s = Soundtrack.Settings

    SoundtrackFrame_EnableMinimapButton:SetChecked(s.EnableMinimapButton)
    SoundtrackFrame_EnableDebugMode:SetChecked(s.Debug)
    SoundtrackFrame_ShowTrackInformation:SetChecked(s.ShowTrackInformation)
    SoundtrackFrame_ShowDefaultMusic:SetChecked(s.ShowDefaultMusic)
    SoundtrackFrame_ShowPlaybackControls:SetChecked(s.ShowPlaybackControls)
    SoundtrackFrame_ShowEventStack:SetChecked(s.ShowEventStack)
    SoundtrackFrame_AutoAddZones:SetChecked(s.AutoAddZones)
    SoundtrackFrame_AutoEscalateBattleMusic:SetChecked(s.EscalateBattleMusic)
    
    SoundtrackFrame_EnableZoneMusic:SetChecked(s.EnableZoneMusic)
    SoundtrackFrame_EnableBattleMusic:SetChecked(s.EnableBattleMusic)
    SoundtrackFrame_EnableMiscMusic:SetChecked(s.EnableMiscMusic)
    SoundtrackFrame_EnableCustomMusic:SetChecked(s.EnableCustomMusic)
    
    local cvar_LoopMusic = GetCVar("Sound_ZoneMusicNoDelay")
    Soundtrack.TraceFrame("Sound_ZoneMusicNoDelay: " .. cvar_LoopMusic)
    if cvar_LoopMusic == "0" then
        SoundtrackFrame_LoopMusic:SetChecked(false)
    else
        SoundtrackFrame_LoopMusic:SetChecked(true)
    end
end

function SoundtrackFrame_ToggleLoopMusic()
    if SoundtrackFrame_LoopMusic:GetChecked() == true then
        SetCVar("Sound_ZoneMusicNoDelay", "1")
    else
        SetCVar("Sound_ZoneMusicNoDelay", "0")
    end
end

function SoundtrackFrame_ToggleMinimapButton()
    Soundtrack.Settings.EnableMinimapButton = not Soundtrack.Settings.EnableMinimapButton
    SoundtrackMinimap_RefreshMinimap()
    
    if not Soundtrack.Settings.EnableMinimapButton then
        Soundtrack.TraceFrame("The minimap button was hidden. You can access Soundtrack's UI by using the /soundtrack command.")
    end
end

function SoundtrackFrame_ToggleDebugMode()
    Soundtrack.Settings.Debug = not Soundtrack.Settings.Debug
    Soundtrack.Util.InitDebugChatFrame()
end

function SoundtrackFrame_ToggleShowTrackInformation()
    Soundtrack.Settings.ShowTrackInformation = not Soundtrack.Settings.ShowTrackInformation
end

function SoundtrackFrame_ToggleShowEventStack()
    Soundtrack.Settings.ShowEventStack = not Soundtrack.Settings.ShowEventStack
    
    SoundtrackFrame_RefreshPlaybackControls()
    
end



function SoundtrackFrame_RefreshPlaybackControls()

    local stopButton = getglobal("SoundtrackControlFrame_StopButton")
    local playButton = getglobal("SoundtrackControlFrame_PlayButton")
    
    if stopButton and playButton then
        if Soundtrack.Events.Paused then
            stopButton:Hide()
            playButton:Show()
        else
            stopButton:Show()
            playButton:Hide()
        end
    end
    
    
    local stopButton2 = getglobal("SoundtrackFrame_StopButton")
    local playButton2 = getglobal("SoundtrackFrame_PlayButton")
    
    if stopButton2 and playButton2 then
        if Soundtrack.Events.Paused then
            stopButton2:Hide()
            playButton2:Show()
        else
            stopButton2:Show()
            playButton2:Hide()
        end
    end

    local controlFrame = getglobal("SoundtrackControlFrame")

    if controlFrame then
        if Soundtrack.Settings.ShowPlaybackControls then
            controlFrame:Show()
        
            if (Soundtrack.Settings.ShowEventStack) then
                SoundtrackControlFrameStackTitle:Show()
                SoundtrackControlFrameStack1:Show()
                SoundtrackControlFrameStack2:Show()
                SoundtrackControlFrameStack3:Show()
                SoundtrackControlFrameStack4:Show()
                SoundtrackControlFrameStack5:Show()
                SoundtrackControlFrameStack6:Show()
                SoundtrackControlFrameStack7:Show()
                SoundtrackControlFrameStack8:Show()
                SoundtrackControlFrameStack9:Show()
                SoundtrackControlFrameStack10:Show()
            else
                SoundtrackControlFrameStackTitle:Hide()
                SoundtrackControlFrameStack1:Hide()
                SoundtrackControlFrameStack2:Hide()
                SoundtrackControlFrameStack3:Hide()
                SoundtrackControlFrameStack4:Hide()
                SoundtrackControlFrameStack5:Hide()
                SoundtrackControlFrameStack6:Hide()
                SoundtrackControlFrameStack7:Hide()
                SoundtrackControlFrameStack8:Hide()
                SoundtrackControlFrameStack9:Hide()
                SoundtrackControlFrameStack10:Hide()
            end
        else
            controlFrame:Hide()
        end
    end
    
    
end


function SoundtrackFrame_ToggleShowPlaybackControls()
    Soundtrack.Settings.ShowPlaybackControls = not Soundtrack.Settings.ShowPlaybackControls
    SoundtrackFrame_RefreshPlaybackControls()
end

function SoundtrackFrame_ToggleRandomMusic()
    local eventTable = Soundtrack.Events.GetTable(self.SelectedEventsTable)
    if eventTable[SoundtrackFrame_SelectedEvent] then
        eventTable[SoundtrackFrame_SelectedEvent].random = not eventTable[SoundtrackFrame_SelectedEvent].random
    end
end

function SoundtrackFrame_ToggleSoundEffect()
    local eventTable = Soundtrack.Events.GetTable(self.SelectedEventsTable)
    if eventTable[SoundtrackFrame_SelectedEvent] then
        eventTable[SoundtrackFrame_SelectedEvent].soundEffect = not eventTable[SoundtrackFrame_SelectedEvent].soundEffect
    end
end

function SoundtrackFrame_ToggleContinuousMusic()
    local eventTable = Soundtrack.Events.GetTable(self.SelectedEventsTable)
    if eventTable[SoundtrackFrame_SelectedEvent] then
        eventTable[SoundtrackFrame_SelectedEvent].continuous = not eventTable[SoundtrackFrame_SelectedEvent].continuous
    end
end

function SoundtrackFrame_OnShow()
    SoundtrackFrame_RefreshCurrentlyPlaying()
    SelectActiveTab()
end

function SoundtrackFrame_OnHide()
    Soundtrack.StopEventAtLevel(10) -- TODO Anthony (Preview music)
    
    if self.SelectedEventsTable ~= "Playlists" then
        Soundtrack.StopEventAtLevel(10) -- TODO Anthony
    end
end


function SoundtrackFrame_RefreshCustomEvent()
      
    local customEvent = Soundtrack_CustomEvents[SoundtrackFrame_SelectedEvent]
    
    if customEvent == nil then
        return
    end
       
    if customEvent then
        -- TODO at startup
        if customEvent.priority == nil then
            customEventPriority = 1
        end
    
        getglobal("SoundtrackFrame_Priority"):SetText(tostring(customEvent.priority))
        getglobal("SoundtrackFrame_CustomContinuous"):SetChecked(customEvent.continuous)
        if customEvent.type == "Event Script" then 
            getglobal("SoundtrackFrame_FontStringTrigger"):SetText("Trigger")
            getglobal("SoundtrackFrame_EventTrigger"):SetText(customEvent.trigger)
            getglobal("SoundtrackFrame_EventScript"):SetText(customEvent.script)
        elseif customEvent.type == "Buff" then
            getglobal("SoundtrackFrame_FontStringTrigger"):SetText("Buff Texture")
            getglobal("SoundtrackFrame_EventTrigger"):SetText(customEvent.buffTexture)
            getglobal("SoundtrackFrame_EventScript"):SetText("Buff events do not need a script.\nThey remain active while the specified buff is active.")
            -- TODO Make readonly
        elseif customEvent.type == "Update Script" then
            getglobal("SoundtrackFrame_FontStringTrigger"):SetText("Trigger")
            getglobal("SoundtrackFrame_EventTrigger"):SetText("OnUpdate")
            getglobal("SoundtrackFrame_EventScript"):SetText(customEvent.script)
            -- TODO Make readonly
        end
    end
    
    
    -- temp
    if customEvent.type == nil then
        Soundtrack.TraceFrame("Nil type on " .. SoundtrackFrame_SelectedEvent)
        customEvent.type = "Update Script"
    end
    
    local eventTypeIndex = Soundtrack.IndexOf(eventTypes, customEvent.type)
    UIDropDownMenu_SetSelectedID(SoundtrackFrame_EventTypeDropDown, eventTypeIndex)
    UIDropDownMenu_SetText(SoundtrackFrame_EventTypeDropDown, customEvent.type)
    --SoundtrackFrame_EventTypeDropDown_OnLoad()
end

function SoundtrackFrameEventButton_OnClick(mouseButton)

    Soundtrack.TraceFrame("EventButton_OnClick")

    Soundtrack.Events.Pause(false)

    local flatEventsTable = GetFlatEventsTable()
    local button = getglobal("SoundtrackFrameEventButton"..this:GetID().."ButtonTextName")
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameEventScrollFrame)
    SoundtrackFrame_SelectedEvent = flatEventsTable[this:GetID() + listOffset].tag -- The event name.
    
    -- TODO only react if clicking the expand/collapse button
    
    local event = Soundtrack_Events[self.SelectedEventsTable][SoundtrackFrame_SelectedEvent]
    if event.expanded then
       event.expanded = false
       Soundtrack.TraceFrame(SoundtrackFrame_SelectedEvent .. " is now collapsed")
    else 
       event.expanded = true
       Soundtrack.TraceFrame(SoundtrackFrame_SelectedEvent .. " is now expanded")
    end
    
    Soundtrack_OnTreeChanged(self.SelectedEventsTable)
    
    SoundtrackFrame_RefreshEvents()
        
    if ( mouseButton == "RightButton" and self.SelectedEventsTable == "Zone") then
        -- Toggle menu
        local menu = getglobal("SoundtrackFrameEventMenu")
        menu.point = "TOPRIGHT"
        menu.relativePoint = "CENTER"
        ToggleDropDownMenu(1, nil, menu, button, 0, 0)
    elseif self.SelectedEventsTable == "Playlists" then
        Soundtrack.PlayEvent(self.SelectedEventsTable, SoundtrackFrame_SelectedEvent)
    end
    
    if self.SelectedEventsTable == "Custom" then
        SoundtrackFrame_RefreshCustomEvent()
    end
end

function SoundtrackFrameAddZoneButton_OnClick()
    Soundtrack.AddEvent("Zone", GetSubZoneText(), 2, true)
    Soundtrack.AddEvent("Zone", GetRealZoneText(), 3, true)
    Soundtrack.AddEvent("Zone", GetMinimapZoneText(), 4, true)
    
    -- Select the newly added area.
    if (GetSubZoneText() ~= nil) then
        SoundtrackFrame_SelectedEvent = GetSubZoneText()
    else
        SoundtrackFrame_SelectedEvent = GetRealZoneText()
    end
    
    SoundtrackFrame_RefreshEvents()
end

function SoundtrackFrameAddTargetButton_OnClick()
    local targetName = UnitName("target")
    if targetName then
        SoundtrackFrame_AddNamedBoss(targetName)
    else
        StaticPopup_Show("SOUNDTRACK_ADD_BOSS")
    end
end

function SoundtrackFrameAddPlaylistButton_OnClick()

    local t = Soundtrack.Events.GetTable("Playlists")
    
    if not t then return end
    
    local numPlaylists = 0
    for k,v in pairs(t) do
        numPlaylists = numPlaylists + 1
    end
    
    local index = numPlaylists + 1

    local playlistName = "Playlist "..index

    Soundtrack.AddEvent("Playlists", playlistName, 10, true)
    SoundtrackFrame_SelectedEvent = playlistName
    Soundtrack_SortEvents("Playlists")
    SoundtrackFrame_RefreshEvents()
end

function SoundtrackFrameDeletePlaylistButton_OnClick()
    Soundtrack.TraceFrame("Deleting " .. SoundtrackFrame_SelectedEvent)
    Soundtrack.Events.DeleteEvent("Playlists", SoundtrackFrame_SelectedEvent)
    SoundtrackFrame_RefreshEvents()
end

function SoundtrackFrameEventMenu_Initialize()
    --[[Title
    local info = {}
    info.text = "Soundtrack"
    info.notClickable = 1
    info.isTitle = 1
    UIDropDownMenu_AddButton(info, 1)]]
    
    -- Remove track
    local info = {}
    info.text = "Remove zone"
    info.value = "RemoveEvent"
    info.func = function() Soundtrack.Events.RemoveEventWithConfirmation() end
    info.notCheckable = 1
    UIDropDownMenu_AddButton(info, 1)
end

function SoundtrackFrame_StatusBar_OnClick(mouseButton)
    Soundtrack.TraceFrame("StatusBar_OnClick")
    --if this:GetName() == "SoundtrackControlFrame_StatusBarEventBorder" then -- event
        -- Toggle menu
        local menu = getglobal("SoundtrackControlFrame_PlaylistMenu")
        local button = getglobal("SoundtrackControlFrame_StatusBarTrack")
        menu.point = "TOPLEFT"
        menu.relativePoint = "BOTTOMLEFT"
        ToggleDropDownMenu(1, nil, menu, button, 0, 0)
    --end
end

function SoundtrackControlFrame_PlaylistMenu_OnClick()
    Soundtrack.TraceFrame("PlaylistMenu_OnClick")

    local table = Soundtrack.Events.GetTable("Playlists")
    Soundtrack.TraceFrame(this:GetID())
    
    local i = 1
    local eventName = nil
    for k,v in pairs(table) do
        if i == this:GetID() then
            eventName = k
        end
        i = i + 1
    end
    
    if eventName then
        Soundtrack.PlayEvent("Playlists", eventName)
    end
end

function SoundtrackControlFrame_PlaylistMenu_Initialize()
    
    local table = Soundtrack.Events.GetTable("Playlists")
    
    for k,v in pairs(table) do
        local info = {}
        info.text = k
        info.value = k
        info.func = SoundtrackControlFrame_PlaylistMenu_OnClick
        info.notCheckable = 1
        UIDropDownMenu_AddButton(info, 1)
    end
end

function SoundtrackFrameTrackMenu_Initialize()
    -- Remove track
    local info = {}
    info.text = "Remove track"
    info.value = "RemoveTrack"
    info.func = function() Soundtrack.Library.RemoveTrackWithConfirmation() end
    info.notCheckable = 1
    UIDropDownMenu_AddButton(info, 1)
end

function SoundtrackFrameTrackCheckBox_OnClick(mouseButton)
    local checkBox = getglobal("SoundtrackFrameTrackButton"..this:GetID().."CheckBox")  
    
    --local button = getglobal("SoundtrackFrameTrackButton"..this:GetID().."ButtonTextName")  
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameTrackScrollFrame)
    SoundtrackFrame_SelectedTrack = Soundtrack_SortedTracks[this:GetID() + listOffset] -- track file name
    
    if SoundtrackFrame_SelectedEvent then
        if (SoundtrackFrame_IsTrackActive(SoundtrackFrame_SelectedTrack)) then
            Soundtrack.Events.Remove(self.SelectedEventsTable, SoundtrackFrame_SelectedEvent, SoundtrackFrame_SelectedTrack)
        else
            -- Add the track to the events list.
            Soundtrack.AssignTrack(SoundtrackFrame_SelectedEvent, SoundtrackFrame_SelectedTrack)
        end
    end

    -- To refresh assigned track counts.
    SoundtrackFrame_RefreshEvents()    
    SoundtrackFrame_RefreshTracks()
end

function SoundtrackFrameAssignedTrackCheckBox_OnClick(mouseButton)
    local checkBox = getglobal("SoundtrackFrameAssignedTrackButton"..this:GetID().."CheckBox")  
    
    --local button = getglobal("SoundtrackFrameAssignedTrackButton"..this:GetID().."ButtonTextName")  
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameAssignedTracksScrollFrame)
    
    local assignedTracks = Soundtrack_Events[self.SelectedEventsTable][SoundtrackFrame_SelectedEvent].tracks    
    SoundtrackFrame_SelectedTrack = assignedTracks[this:GetID() + listOffset] -- track file name
    
    if (SoundtrackFrame_IsTrackActive(SoundtrackFrame_SelectedTrack)) then
        Soundtrack.Events.Remove(self.SelectedEventsTable, SoundtrackFrame_SelectedEvent, SoundtrackFrame_SelectedTrack)
    else
        -- Add the track to the events list.
        Soundtrack.AssignTrack(SoundtrackFrame_SelectedEvent, SoundtrackFrame_SelectedTrack)
    end

    -- To refresh assigned track counts.
    SoundtrackFrame_RefreshEvents()    
    SoundtrackFrame_RefreshTracks()
end

-- Plays a track using a temporary "preview" event on stack level 7
function PlayPreviewTrack(trackName)
    -- Make sure the preview event exists
    Soundtrack.Events.DeleteEvent("Misc", "Preview")
    Soundtrack.AddEvent("Misc", "Preview", 10, true)
    Soundtrack.AssignTrack("Preview", trackName)
    Soundtrack.PlayEvent("Misc", "Preview", true)
end

function SoundtrackFrameTrackButton_OnClick(mouseButton)
    
    Soundtrack.TraceFrame("OnClick")
    
    Soundtrack.Events.Pause(false)
    
    --local button = getglobal("SoundtrackFrameTrackButton"..this:GetID().."ButtonTextName")
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameTrackScrollFrame)
    SoundtrackFrame_SelectedTrack = Soundtrack_SortedTracks[this:GetID() + listOffset] -- track file name
    
    PlayPreviewTrack(SoundtrackFrame_SelectedTrack)    
    
    SoundtrackFrame_RefreshTracks()
end

function SoundtrackFrameAssignedTrackButton_OnClick(mouseButton)
    
    Soundtrack.Events.Pause(false)
    
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameAssignedTracksScrollFrame)
    
    local assignedTracks = Soundtrack_Events[self.SelectedEventsTable][SoundtrackFrame_SelectedEvent].tracks
    
    SoundtrackFrame_SelectedTrack = assignedTracks[this:GetID() + listOffset] -- track file name
    
    PlayPreviewTrack(SoundtrackFrame_SelectedTrack)    
    
    SoundtrackFrame_RefreshTracks()
end

function SoundtrackFrameAllButton_OnClick()
    -- Start by clearing all tracks
    Soundtrack.Events.ClearEvent(self.SelectedEventsTable, SoundtrackFrame_SelectedEvent)
    
    -- The highlight all of them
    local i
    for i=1, getn(Soundtrack_SortedTracks), 1 do
        Soundtrack.AssignTrack(SoundtrackFrame_SelectedEvent, Soundtrack_SortedTracks[i])
    end
    SoundtrackFrame_RefreshEvents()
end

function SoundtrackFrameClearButton_OnClick()
    if not SoundtrackFrame_SelectedEvent then
        Soundtrack.Error("The Clear button was enabled without a selected event")
        return
    end
    
    -- TODO Confirm
    
    Soundtrack.Events.ClearEvent(self.SelectedEventsTable, SoundtrackFrame_SelectedEvent)
    
    SoundtrackFrame_RefreshEvents()
end

function SoundtrackFrameRemoveZoneButton_OnClick()
end

function SoundtrackFrameTab_OnClick()
    -- Battle events tab
    if (SoundtrackFrame.selectedTab == 1) then
        self.SelectedEventsTable = "Battle"
        SoundtrackFrameEventFrame:Show()
        SoundtrackFrameOptionsFrame:Hide()
    elseif (SoundtrackFrame.selectedTab == 2) then
        self.SelectedEventsTable = "Boss"
        SoundtrackFrameEventFrame:Show()
        SoundtrackFrameOptionsFrame:Hide()
    -- Zones tab
    elseif (SoundtrackFrame.selectedTab == 3) then
        self.SelectedEventsTable = "Zone"
        SoundtrackFrameEventFrame:Show()
        SoundtrackFrameOptionsFrame:Hide()
    -- Dance tab
    elseif (SoundtrackFrame.selectedTab == 4) then
        self.SelectedEventsTable = "Dance"
        SoundtrackFrameEventFrame:Show()
        SoundtrackFrameOptionsFrame:Hide()
    elseif (SoundtrackFrame.selectedTab == 5) then
        self.SelectedEventsTable = "Misc"
        SoundtrackFrameEventFrame:Show()
        SoundtrackFrameOptionsFrame:Hide()
    elseif (SoundtrackFrame.selectedTab == 6) then
        self.SelectedEventsTable = "Custom"
        SoundtrackFrameEventFrame:Show()
        SoundtrackFrameOptionsFrame:Hide()
    elseif (SoundtrackFrame.selectedTab == 7) then
        self.SelectedEventsTable = "Playlists"
        SoundtrackFrameEventFrame:Show()
        SoundtrackFrameOptionsFrame:Hide()
    -- Options tab
    elseif (SoundtrackFrame.selectedTab == 8) then
        self.SelectedEventsTable = nil
        SoundtrackFrameEventFrame:Hide()
        SoundtrackFrameOptionsFrame:Show()
    end

    SoundtrackFrame_OnTabChanged()
end

function SoundtrackFrame_OnTabChanged()
    
    if (self.SelectedEventsTable == nil) then
    
    else
        Soundtrack.StopEvent("Misc", "Preview") -- Stop preview track
        
        -- Select first event if possible 
        SoundtrackFrame_SelectedEvent = nil
        
        local table = GetFlatEventsTable()
        
        if table and getn(GetFlatEventsTable()) >= 1 then
            SoundtrackFrame_SelectedEvent = table[1].tag
        end
        
        SoundtrackFrame_RefreshEvents()
            
        if self.SelectedEventsTable == "Zone" then
            SoundtrackFrameAddZoneButton:Show()
        else
            SoundtrackFrameAddZoneButton:Hide()
        end
        
        
        if self.SelectedEventsTable == "Boss" then
            SoundtrackFrameAddTargetButton:Show()
            SoundtrackFrameDeleteTargetButton:Show()
        else
            SoundtrackFrameAddTargetButton:Hide()
            SoundtrackFrameDeleteTargetButton:Hide()
        end
        
        if self.SelectedEventsTable == "Custom" then
            SoundtrackFrameAddCustomEventButton:Show()
            SoundtrackFrameEditCustomEventButton:Show()
            SoundtrackFrameDeleteCustomEventButton:Show()
        else
            SoundtrackFrameAddCustomEventButton:Hide()
            SoundtrackFrameEditCustomEventButton:Hide()
            SoundtrackFrameDeleteCustomEventButton:Hide()
            getglobal("SoundtrackFrameRightPanelTracks"):Show()
            getglobal("SoundtrackFrameRightPanelEditEvent"):Hide()
        end
        
        if self.SelectedEventsTable == "Playlists" then
            SoundtrackFrameAddPlaylistButton:Show()
            SoundtrackFrameDeletePlaylistButton:Show()
        else
            SoundtrackFrameAddPlaylistButton:Hide()
            SoundtrackFrameDeletePlaylistButton:Hide()
        end
        
        if self.SelectedEventsTable == "Playlists" or
           self.SelectedEventsTable == "Custom" then
        end
        
        if self.SelectedEventsTable ~= "Options" then
            SoundtrackFrame_OnSelectedEventTabChanged()
        end
        
        if self.SelectedEventsTable ~= "Playlists" then
            Soundtrack.StopEventAtLevel(10) -- Stop playlists when we go out of the playlist panel
        end
    end
end

function SoundtrackFrame_OnFilterChanged()
    Soundtrack.trackFilter = SoundtrackFrame_TrackFilter:GetText()
    Soundtrack.SortTracks()
end

function SoundtrackFrame_DisableAllEventButtons()
    for i = 1, EVENTS_TO_DISPLAY, 1 do
        local button = getglobal("SoundtrackFrameEventButton"..i)
        button:Hide()
    end
end

function SoundtrackFrame_DisableAllTrackButtons()
    for i = 1, TRACKS_TO_DISPLAY, 1 do
        local button = getglobal("SoundtrackFrameTrackButton"..i)
        button:Hide()
    end
end

function SoundtrackFrame_DisableAllAssignedTrackButtons()
    for i = 1, ASSIGNED_TRACKS_TO_DISPLAY, 1 do
        local button = getglobal("SoundtrackAssignedTrackButton"..i)
        button:Hide()
    end
end



-- Replaces each folder in an event path with spaces
local function GetLeafText(eventPath)
    if eventPath then
        return string.gsub(eventPath, "[^/]*/", "    ")
    else
        return eventPath
    end
end

-- Counts the number of / in a path to calculate the depth
local function GetEventDepth(eventPath)
   local count = 0    
   local i = 0    
   while true do
      i = string.find(eventPath, "/", i+1)
    -- find 'next' newline
      if i == nil then 
	 return count 
      end      
      count = count + 1    
   end
end



function SoundtrackFrame_RefreshEvents()
    if not SoundtrackFrame:IsVisible() or not self.SelectedEventsTable then
        return
    end
    
    -- TODO Should not have to do this here
    local flatEventsTable = GetFlatEventsTable()
    
    -- The selected event was deleted, activate another one if possible
    if self.SelectedEventsTable and SoundtrackFrame_SelectedEvent  then
        if not Soundtrack_Events[self.SelectedEventsTable][SoundtrackFrame_SelectedEvent] then
            if table.getn(flatEventsTable) > 0 then
                SoundtrackFrame_SelectedEvent = flatEventsTable[1].tag
            else
                SoundtrackFrame_SelectedEvent = ""
            end
        end
    end
    
    SoundtrackFrame_DisableAllEventButtons()
    local numEvents = table.getn(flatEventsTable)
    
    local nameText
    local name
    local button
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameEventScrollFrame)

    local buttonIndex

    local stackLevel = Soundtrack.Events.GetCurrentStackLevel()
    local currentEvent = nil
    if stackLevel ~= 0 then
        currentEvent = Soundtrack.Events.Stack[stackLevel].eventName
    end
    
    for i, eventNode in ipairs(flatEventsTable) do
       local eventName = eventNode.tag or error("nil event!")
    
        if (i > listOffset and i < listOffset + EVENTS_TO_DISPLAY) then
            buttonIndex = i - listOffset
            if (buttonIndex <= EVENTS_TO_DISPLAY) then
            
                --nameText = getglobal("SoundtrackFrameEventButton"..buttonIndex.."ButtonTextName")
                --nameText:SetText(GetLeafText(selectedSortedEventsTable[i]))
                button = getglobal("SoundtrackFrameEventButton"..buttonIndex)
                
                -- TODO use node.name + depth space?
                button:SetText(GetLeafText(eventName))
                button:SetID(buttonIndex)
                button:Show()
                
                local event = Soundtrack_Events[self.SelectedEventsTable][eventName]

                -- TODO Make sure nodes is always initialized
                local highlightButton = getglobal("SoundtrackFrameEventButton"..buttonIndex.."Highlight") or error("Missing highlight " .. i)
                local expandable = eventNode.nodes and table.getn(eventNode.nodes) >= 1
                if expandable then
                    if event.expanded then
                        button:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up")
                    else
                        button:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up")
                    end
                    highlightButton:SetTexture("Interface\\Buttons\\UI-PlusButton-Hilight")
                    button:UnlockHighlight()
                else
                    highlightButton:SetTexture("")
                    button:SetNormalTexture("")
                end    

                -- Show number of assigned tracks
                local assignedText = getglobal("SoundtrackFrameEventButton"..buttonIndex.."ButtonTextAssigned")
                if event then 
                    local numAssignedTracks = table.getn(event.tracks)
                    if (numAssignedTracks == 0) then
                        assignedText:SetText("")
                    else
                        assignedText:SetText("("..numAssignedTracks..")")
                    end
                end
                
                icon = getglobal("SoundtrackFrameEventButton"..buttonIndex.."Icon")
                icon:Hide()
                
                -- Update the highlight if that track is active for the event.
                -- Todo : does this work?
                if (eventName == SoundtrackFrame_SelectedEvent) then
                    button:LockHighlight()
                else
                    button:UnlockHighlight()
                end
                
                -- Update the icon
                if currentEvent == eventName then
                    icon:Show()
                end
            end
        end
        --i = i + 1    
    end
    
    -- ScrollFrame stuff
    FauxScrollFrame_Update(SoundtrackFrameEventScrollFrame, numEvents + 1, EVENTS_TO_DISPLAY, EVENTS_ITEM_HEIGHT )    
    
    SoundtrackFrame_RefreshTracks()
    --SoundtrackFrame_RefreshCurrentlyPlaying()
    RefreshEventSettings()
end

function SoundtrackFrame_RenameEvent()
    
    
    if SoundtrackFrame_SelectedEvent and not suspendRenameEvent then
        Soundtrack.Events.RenameEvent(self.SelectedEventsTable, 
            SoundtrackFrame_SelectedEvent, 
            getglobal("SoundtrackFrame_EventName"):GetText())
        SoundtrackFrame_RefreshEvents()
    end
end

-- Checks if a particular track is already set for an event
function SoundtrackFrame_IsTrackActive(trackName)

    local event = Soundtrack_Events[self.SelectedEventsTable][SoundtrackFrame_SelectedEvent]
    if not event then
        return false
    end
    
    for i,tn in ipairs(event.tracks) do
        if (tn == trackName) then
            return true
        end
    end
    
    return false
end

local cooldowns = { 0, 1, 2, 3, 5, 10, 15, 30 }

local function GetBattleCooldowns()
    return {
        "No cooldown",
        "1 second",
        "2 seconds",
        "3 seconds",
        "5 seconds",
        "10 seconds",
        "15 seconds",
        "30 seconds",
    }
end

local function GetCurrentBattleCooldown()
-- TODO replace with IndexOf
    for i,c in ipairs(cooldowns) do
        if Soundtrack.Settings.BattleCooldown == c then
            return i
        end
    end
    
    return 1
end






local silences = { 0, 5, 10, 20, 30, 40, 60, 90, 120 }

local function GetSilences()
    return {
        "No silence",
        "5 seconds",
        "10 seconds",
        "20 seconds",
        "30 seconds",
        "40 seconds",
        "1 minute",
        "1.5 minute",
        "2 minutes"
    }
end

local function GetCurrentSilence()
-- Replace with index of
    local i
    for i=1, getn(silences), 1 do
        if (Soundtrack.Settings.Silence == silences[i]) then
            return i
        end
    end
    
    return 1
end



function SoundtrackFrame_Toggle()
    if (SoundtrackFrame:IsVisible()) then
        SoundtrackFrame:Hide()
    else
        SoundtrackFrame:Show() -- TODO Call command?
    end
end

function SoundtrackFrame_BattleCooldownDropDown_OnLoad()
    
    SoundtrackFrame.selectedCooldown = GetCurrentBattleCooldown()
    UIDropDownMenu_SetSelectedID(this, SoundtrackFrame.selectedCooldown)
    UIDropDownMenu_Initialize(this, SoundtrackFrame_BattleCooldownDropDown_Initialize)
    UIDropDownMenu_SetWidth(this, 130)
end

function SoundtrackFrame_EventTypeDropDown_OnLoad()
    UIDropDownMenu_Initialize(this, SoundtrackFrame_EventTypeDropDown_Initialize)
    UIDropDownMenu_SetWidth(this, 130)
end

function SoundtrackFrame_BattleCooldownDropDown_LoadCooldowns(cooldownTexts)
    local currentCooldown = SoundtrackFrame.selectedCooldown
    local info
    
    for i,cooldownText in ipairs(cooldownTexts) do
        local checked = nil
        if currentCooldown == i then
            checked = 1
            UIDropDownMenu_SetText(SoundtrackFrame_BattleCooldownDropDown, cooldownText)
        end

        info = {}
        info.text = cooldownText
        info.func = SoundtrackFrame_BattleCooldownDropDown_OnClick
        info.checked = checked
        UIDropDownMenu_AddButton(info)
    end
end



function SoundtrackFrame_BattleCooldownDropDown_Initialize()
    SoundtrackFrame_BattleCooldownDropDown_LoadCooldowns(GetBattleCooldowns())    
end

function SoundtrackFrame_EventTypeDropDown_AddInfo(id, caption)
    local info = UIDropDownMenu_CreateInfo()
    info.value = id
    info.text = caption
    info.func = SoundtrackFrame_EventTypeDropDown_OnClick
    local checked = nil
    local selectedId = UIDropDownMenu_GetSelectedID(SoundtrackFrame_EventTypeDropDown)
    if (selectedId ~= nil and selectedId == id) then
        checked = 1
    end
    info.checked = checked
    UIDropDownMenu_AddButton(info)
end

function SoundtrackFrame_EventTypeDropDown_Initialize()
    for i=1, getn(eventTypes) do
        SoundtrackFrame_EventTypeDropDown_AddInfo(i, eventTypes[i])
    end
end



function SoundtrackFrame_BattleCooldownDropDown_OnClick()
    UIDropDownMenu_SetSelectedID(SoundtrackFrame_BattleCooldownDropDown, this:GetID())
    SoundtrackFrame.selectedCooldown = this:GetID()
    -- Save settings.
    Soundtrack.Settings.BattleCooldown = cooldowns[SoundtrackFrame.selectedCooldown]
end

function SoundtrackFrame_EventTypeDropDown_OnClick()
    
    local oldSelectedId = UIDropDownMenu_GetSelectedID(SoundtrackFrame_EventTypeDropDown)
    local selectedId = this:GetID()
    
    if ( selectedId == oldSelectedId) then
        return
    end
    
    local customEvent = Soundtrack_CustomEvents[SoundtrackFrame_SelectedEvent]

    customEvent.type = eventTypes[selectedId]
    
    if eventTypes[selectedId] == "Update Script" then
        if customEvent.script == nil then
            customEvent.swcript = "type your update script here"
        end
    elseif eventTypes[selectedId] == "Buff" then
        if customEvent.buffTexture == nil then
           customEvent.buffTexture = "Interface\\Icons\\Ability_Rogue_Sprint" 
        end
    elseif eventTypes[selectedId] == "Event Script" then
        if customEvent.trigger == nil then
            customEvent.trigger = "PLAYER_AURAS_CHANGED"
        end
        if customEvent.script == nil then
            customEvent.script = "type in your event script here"
        end
    end
    
    SoundtrackFrame_RefreshCustomEvent()
end

function SoundtrackFrame_SilenceDropDown_OnLoad()
    
    SoundtrackFrame.selectedSilence = GetCurrentSilence()
    UIDropDownMenu_SetSelectedID(SoundtrackFrame_SilenceDropDown, SoundtrackFrame.selectedSilence)
    UIDropDownMenu_Initialize(SoundtrackFrame_SilenceDropDown, SoundtrackFrame_SilenceDropDown_Initialize)
    UIDropDownMenu_SetWidth(SoundtrackFrame_SilenceDropDown, 130)
end

function SoundtrackFrame_SilenceDropDown_LoadSilences(silencesTexts)
    local currentSilence = SoundtrackFrame.selectedSilence
    local info
    
    for i=1, getn(silencesTexts), 1 do
        local checked = nil
        if ( currentSilence == i ) then
            checked = 1
			UIDropDownMenu_SetText(SoundtrackFrame_SilenceDropDown, silencesTexts[i])
        end

        info = {}
        info.text = silencesTexts[i]
        info.func = SoundtrackFrame_SilenceDropDown_OnClick
        info.checked = checked
        UIDropDownMenu_AddButton(info)
    end
end

function SoundtrackFrame_SilenceDropDown_Initialize()
    SoundtrackFrame_SilenceDropDown_LoadSilences(GetSilences())    
end

function SoundtrackFrame_SilenceDropDown_OnClick()
    UIDropDownMenu_SetSelectedID(SoundtrackFrame_SilenceDropDown, this:GetID())
    SoundtrackFrame.selectedSilence = this:GetID()
    -- Save settings.
    Soundtrack.Settings.Silence = silences[SoundtrackFrame.selectedSilence]
end

-- TODO Anthony : Refresh when no events is selected (right now the checks from the last thing
-- get shown and you can check things on/off anyways.
function SoundtrackFrame_RefreshTracks()

    if (not SoundtrackFrame:IsVisible() or self.SelectedEventsTable == nil) then
        return
    end

    SoundtrackFrame_DisableAllTrackButtons()
    local numTracks = table.getn(Soundtrack_SortedTracks)
    local nameText
    local name
    local icon
    local button
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameTrackScrollFrame)
    local buttonIndex
    --local i=1
    --for key,value in Soundtrack_Tracks do
    for i = 1, numTracks, 1 do
        if (i > listOffset and i < listOffset + TRACKS_TO_DISPLAY) then
            buttonIndex = i - listOffset
            if (buttonIndex <= TRACKS_TO_DISPLAY) then
                
                local nameText = getglobal("SoundtrackFrameTrackButton"..buttonIndex.."ButtonTextName")
                
                if SoundtrackFrame.nameHeaderType == "filePath" or SoundtrackFrame.nameHeaderType == nil then
                    nameText:SetText(Soundtrack_SortedTracks[i])
                elseif SoundtrackFrame.nameHeaderType == "fileName" then
                    nameText:SetText(Soundtrack.GetPathFileName(Soundtrack_SortedTracks[i]))
                elseif SoundtrackFrame.nameHeaderType == "title" then
                    nameText:SetText(Soundtrack_Tracks[Soundtrack_SortedTracks[i]].title)
                end
                
                local albumText = getglobal("SoundtrackFrameTrackButton"..buttonIndex.."ButtonTextAlbum")
                albumText:SetText(Soundtrack_Tracks[Soundtrack_SortedTracks[i]].album)
                
                local artistText = getglobal("SoundtrackFrameTrackButton"..buttonIndex.."ButtonTextArtist")
                artistText:SetText(Soundtrack_Tracks[Soundtrack_SortedTracks[i]].artist)
                
                button = getglobal("SoundtrackFrameTrackButton"..buttonIndex)
                button:SetID(buttonIndex)
                button:Show()
                
                -- Show duration of track
                local durationLabel = getglobal("SoundtrackFrameTrackButton"..buttonIndex.."ButtonTextDuration")
                local duration = Soundtrack_Tracks[Soundtrack_SortedTracks[i]].length
                durationLabel:SetText(Soundtrack.Util.FormatDuration(duration))
                
                icon = getglobal("SoundtrackFrameTrackButton"..buttonIndex.."Icon")
                icon:Hide()
                
                local checkBox = getglobal("SoundtrackFrameTrackButton"..buttonIndex.."CheckBox")
                checkBox:SetID(buttonIndex)
                
                if (Soundtrack_SortedTracks[i] == SoundtrackFrame_SelectedTrack) then
                    button:LockHighlight()
                else
                    button:UnlockHighlight()
                end
                
                if (SoundtrackFrame_SelectedEvent ~= nil) then
                    -- Update the highlight if that track is active for the event.
                    if (SoundtrackFrame_IsTrackActive(Soundtrack_SortedTracks[i])) then
                        checkBox:SetChecked(true)    
                    else
                        checkBox:SetChecked(false)
                    end
                    
                    -- Update the icon
                    if (Soundtrack.Library.CurrentlyPlayingTrack == Soundtrack_SortedTracks[i]) then
                        icon:Show()
                    end
                end
                
                if ( buttonIndex > numTracks ) then
                    --ignoreButton:Hide()
                else
                    --ignoreButton:Show()
                end
            end
        end
        --i = i + 1    
    end
    
    -- ScrollFrame stuff
    FauxScrollFrame_Update(SoundtrackFrameTrackScrollFrame, numTracks+1, TRACKS_TO_DISPLAY, EVENTS_ITEM_HEIGHT )
    
    SoundtrackFrame_RefreshAssignedTracks()
end




local function SoundtrackFrame_RefreshUpDownButtons()
    local eventTable = Soundtrack.Events.GetTable(self.SelectedEventsTable)
    if (eventTable[SoundtrackFrame_SelectedEvent] ~= nil) then
        local event = eventTable[SoundtrackFrame_SelectedEvent]
        local currentIndex = Soundtrack.IndexOf(event.tracks, SoundtrackFrame_SelectedTrack)
        
        if (currentIndex > 0 and currentIndex > 1) then
            getglobal("SoundtrackFrameMoveUp"):Enable()    
        else
            getglobal("SoundtrackFrameMoveUp"):Disable()    
        end
        
        if (currentIndex > 0 and currentIndex < getn(event.tracks)) then
            getglobal("SoundtrackFrameMoveDown"):Enable()    
        else
            getglobal("SoundtrackFrameMoveDown"):Disable()    
        end
        
    end
end

function SoundtrackFrame_RefreshAssignedTracks()

    if (not SoundtrackFrame:IsVisible() or self.SelectedEventsTable == nil) then
        return
    end

    SoundtrackFrame_DisableAllAssignedTrackButtons()
    
    if (SoundtrackFrame_SelectedEvent == nil) then
        return
    end
    
    local event = Soundtrack_Events[self.SelectedEventsTable][SoundtrackFrame_SelectedEvent]
    if event == nil then
       return
    end
    
    local priorityText
    if (event.priority == nil) then
        priorityText = "Priority: " .. "Unset"
    else
        priorityText = "Priority: " .. event.priority
    end
    
    local nameText
    local name
    local icon
    local button
    local listOffset = FauxScrollFrame_GetOffset(SoundtrackFrameAssignedTracksScrollFrame)
    local buttonIndex
    --local i=1
    --for key,value in Soundtrack_Tracks do
    
    local assignedTracks = event.tracks
    
    local i

    for i = 1, getn(assignedTracks), 1 do
        if (i > listOffset and i < listOffset + ASSIGNED_TRACKS_TO_DISPLAY) then
            buttonIndex = i - listOffset
            if (buttonIndex <= ASSIGNED_TRACKS_TO_DISPLAY) then
                
                local nameText = getglobal("SoundtrackAssignedTrackButton"..buttonIndex.."ButtonTextName")
                
                if SoundtrackFrame.nameHeaderType == "filePath" or SoundtrackFrame.nameHeaderType == nil then
                    nameText:SetText(assignedTracks[i])
                elseif SoundtrackFrame.nameHeaderType == "fileName" then
                    nameText:SetText(Soundtrack.GetPathFileName(assignedTracks[i]))
                elseif SoundtrackFrame.nameHeaderType == "title" then
                    nameText:SetText(Soundtrack_Tracks[assignedTracks[i]].title)
                end
                
                local albumText = getglobal("SoundtrackAssignedTrackButton"..buttonIndex.."ButtonTextAlbum")
                albumText:SetText(Soundtrack_Tracks[assignedTracks[i]].album)
                
                local artistText = getglobal("SoundtrackAssignedTrackButton"..buttonIndex.."ButtonTextArtist")
                artistText:SetText(Soundtrack_Tracks[assignedTracks[i]].artist)
                
                button = getglobal("SoundtrackAssignedTrackButton"..buttonIndex)
                button:SetID(buttonIndex)
                button:Show()
                
                -- Show duration of track
                local durationLabel = getglobal("SoundtrackAssignedTrackButton"..buttonIndex.."ButtonTextDuration")
                local duration = Soundtrack_Tracks[assignedTracks[i]].length
                durationLabel:SetText(Soundtrack.Util.FormatDuration(duration))
                
                icon = getglobal("SoundtrackAssignedTrackButton"..buttonIndex.."Icon")
                icon:Hide()
                
                local checkBox = getglobal("SoundtrackAssignedTrackButton"..buttonIndex.."CheckBox")
                checkBox:SetID(buttonIndex)
                
                if (assignedTracks[i] == SoundtrackFrame_SelectedTrack) then
                    button:LockHighlight()
                else
                    button:UnlockHighlight()
                end
                
                if (SoundtrackFrame_SelectedEvent ~= nil) then
                    -- Update the highlight if that track is active for the event.
                    if (SoundtrackFrame_IsTrackActive(assignedTracks[i])) then
                        checkBox:SetChecked(true)
                    else
                        checkBox:SetChecked(false)
                    end
                    
                    
                    -- Update the icon
                    if (Soundtrack.Library.CurrentlyPlayingTrack == assignedTracks[i]) then
                        icon:Show()
                    end
                end
                
                if ( buttonIndex > getn(assignedTracks) ) then
                    --ignoreButton:Hide()
                else
                    --ignoreButton:Show()
                end
            end
        end
        --i = i + 1    
    end
    
    -- ScrollFrame stuff
    FauxScrollFrame_Update(SoundtrackFrameAssignedTracksScrollFrame, getn(assignedTracks)+1, ASSIGNED_TRACKS_TO_DISPLAY, EVENTS_ITEM_HEIGHT )
    
    SoundtrackFrame_RefreshUpDownButtons()
end




function SoundtrackFrame_MoveAssignedTrack(direction)
    local eventTable = Soundtrack.Events.GetTable(self.SelectedEventsTable)
    if (eventTable[SoundtrackFrame_SelectedEvent] ~= nil) then
        local event = eventTable[SoundtrackFrame_SelectedEvent]
        local currentIndex = Soundtrack.IndexOf(event.tracks, SoundtrackFrame_SelectedTrack)

        if (currentIndex > 0) then
            if (direction < 0 and currentIndex > 1) then
                -- Move up
                local newIndex = currentIndex - 1
                local temp = event.tracks[newIndex]
                event.tracks[newIndex] = event.tracks[currentIndex]
                event.tracks[currentIndex] = temp
            elseif (direction > 0 and currentIndex < getn(event.tracks)) then
                -- Move down
                local newIndex = currentIndex + 1
                local temp = event.tracks[newIndex]
                event.tracks[newIndex] = event.tracks[currentIndex]
                event.tracks[currentIndex] = temp
            end
        end
        
        SoundtrackFrame_RefreshAssignedTracks()
    end
    
end

function SoundtrackFrameAddCustomEventButton_OnClick()
    getglobal("SoundtrackFrameRightPanelTracks"):Hide()
    getglobal("SoundtrackFrameRightPanelEditEvent"):Show()
    
    -- Find first available name
    local name = "New Event"
    local index = 1
    
    local indexedName = name .. " " .. index
    
    while Soundtrack.GetEvent("Custom", indexedName) ~= nil do
        index = index + 1
        indexedName = name .. " " .. index
    end
    
    local script = "-- Custom script\nSoundtrack.PlayEvent(\"Custom\", " .. indexedName .. ")"
    
    Soundtrack.CustomEvents.RegisterEventScript(indexedName, "Custom", "PLAYER_AURAS_CHANGED", 4, true, 
        script) 
    SoundtrackFrame_SelectedEvent = indexedName
    SoundtrackFrame_RefreshEvents()
    SoundtrackFrame_RefreshCustomEvent()
end



function SoundtrackFrameEditCustomEventButton_OnClick()
    getglobal("SoundtrackFrameRightPanelTracks"):Hide()
    getglobal("SoundtrackFrameRightPanelEditEvent"):Show()
    
    SoundtrackFrame_RefreshCustomEvent()
end

function SoundtrackFrameSaveCustomEventButton_OnClick()
    Soundtrack.TraceFrame("Saving " .. SoundtrackFrame_SelectedEvent)
    local customEvent = Soundtrack_CustomEvents[SoundtrackFrame_SelectedEvent]
    
    customEvent.priority = tonumber(getglobal("SoundtrackFrame_Priority"):GetText())
    customEvent.continuous = getglobal("SoundtrackFrame_CustomContinuous"):GetChecked()
    
    local eventTable = Soundtrack.Events.GetTable("Custom")
    if (eventTable[SoundtrackFrame_SelectedEvent] ~= nil) then
        eventTable[SoundtrackFrame_SelectedEvent].priority = customEvent.priority
        eventTable[SoundtrackFrame_SelectedEvent].continuous = customEvent.continuous
    end
    
    local eventType = customEvent.type
    if eventType == "Event Script" then
        customEvent.trigger = getglobal("SoundtrackFrame_EventTrigger"):GetText()   
        customEvent.script = getglobal("SoundtrackFrame_EventScript"):GetText()
    elseif eventType == "Buff" then
        customEvent.buffTexture = getglobal("SoundtrackFrame_EventTrigger"):GetText()
        customEvent.script = getglobal("SoundtrackFrame_EventScript"):GetText()
    elseif eventType == "Update Script" then
        customEvent.script = getglobal("SoundtrackFrame_EventScript"):GetText()
    end
    customEvent.script = getglobal("SoundtrackFrame_EventScript"):GetText() 
    
    
    getglobal("SoundtrackFrameRightPanelEditEvent"):Hide()
    getglobal("SoundtrackFrameRightPanelTracks"):Show()
end

function SoundtrackFrameDeleteCustomEventButton_OnClick()

    --[[for i=1, getn(Soundtrack_CustomEvents) do
        if Soundtrack_CustomEvents[i] == SoundtrackFrame_SelectedEvent then
            table.remove(Soundtrack_CustomEvents, i)
            Soundtrack.TraceFrame("Deleted custom event: " .. SoundtrackFrame_SelectedEvent)
        end
    end]]
    Soundtrack_CustomEvents[SoundtrackFrame_SelectedEvent] = nil
    Soundtrack.Events.DeleteEvent("Custom", SoundtrackFrame_SelectedEvent)
end

function serialize (o)
  if type(o) == "number" then
    return tostring(o)
  elseif type(o) == "string" then
    return string.format("%q", o)
  elseif type(o) == "table" then
    local result
    result = "{\n"
    for k,v in pairs(o) do
        local val = serialize(v)
        if val ~= nil then
          result = result .. "  [\"" .. k .. "\"] = "
          result = result .. val
          result = result .. ",\n"
        end
    end
    result = result .. "}\n"
    return result
  else
    error("cannot serialize a " .. type(o))
  end
end

function SoundtrackFrameExportSettings_OnClick()
    Soundtrack.Error("Not implemented yet")
    --local result
    --result = "Soundtrack_CustomEvents = "
    --result = result .. serialize(Soundtrack_CustomEvents)
    
    --Soundtrack.TraceFrame(result)
end

function SoundtrackFrameImportSettings_OnClick()
    Soundtrack.Error("Not implemented yet")
   --local text
    --RunScript(text)
end

function SoundtrackFrameDeleteTargetButton_OnClick()
    Soundtrack.TraceFrame("Deleting " .. SoundtrackFrame_SelectedEvent)
    Soundtrack.Events.DeleteEvent("Boss", SoundtrackFrame_SelectedEvent)
    SoundtrackFrame_RefreshEvents()
end